/* Copyright (C) 2021 Rain */

/* This file is part of XNIX. */

/* 
  XNIX is free software: you can redistribute it and/or modify 
  it under the terms of the GNU General Public License as published by 
  the Free Software Foundation, either version 3 of the License, or 
  (at your option) and later version. 
*/

/*
  XNIX is distributed in the hope that it will be useful, 
  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
  GNU General Public License for more details. 
*/

/*
  You should have received a copy of the GNU General Public License 
   along with XNIX. If not, see <https://www.gnu.org/licenses/>.  
*/



#ifndef _KINT_H
#define _KINT_H

#ifndef __ASM__

#include <kernel/types.h>
#include <kernel/errno.h>



/* kernel/trap.S */

void divide_error(void);
void debug(void);
void nmi(void);
void int3(void);
void overflow(void);
void bound(void);
void invalid_code(void);
void device_not_avaliable(void);
void double_fault(void);
void fpu_segment_overrun(void);
void invalid_tss(void);
void segment_not_present(void);
void stack_error(void);
void general_protection(void);
void page_fault(void);
void reserved(void);
void fpu_error(void);
void alignment(void);
void machine(void);
void simd(void);
void virtualization(void);

void irq0x20_interrupt(void);
void irq0x21_interrupt(void);
void irq0x22_interrupt(void);
void irq0x23_interrupt(void);
void irq0x24_interrupt(void);
void irq0x25_interrupt(void);
void irq0x26_interrupt(void);
void irq0x27_interrupt(void);
void irq0x28_interrupt(void);
void irq0x29_interrupt(void);
void irq0x2a_interrupt(void);
void irq0x2b_interrupt(void);
void irq0x2c_interrupt(void);
void irq0x2d_interrupt(void);
void irq0x2e_interrupt(void);
void irq0x2f_interrupt(void);

void register_irq(int, void *, const void *);
void set_irq(int, const void *);
void unregister_irq(int);

/* kernel/timer.S */
void do_irq(const __uint64_t *, __uint64_t);

void do_timer(void);
void do_keyboard(void);

void trace_irq(void);


/* kernel/timer.S */
extern __uint64_t jiffies;


#define IRQ_SAVE_ALL()		\
	"pushq %rax;\n\t"	\
	"pushq %rcx;\n\t"	\
	"pushq %rbx;\n\t"	\
	"pushq %rdx;\n\t"	\
	"pushq %rbp;\n\t"	\
	"pushq %rsi;\n\t"	\
	"pushq %rdi;\n\t"	\
	"pushq %r8; \n\t"	\
	"pushq %r9; \n\t"	\
	"pushq %r10;\n\t"	\
	"pushq %r11;\n\t"	\
	"pushq %r12;\n\t"	\
	"pushq %r13;\n\t"	\
	"pushq %r14;\n\t"	\
	"pushq %r15;\n\t"	\
	"movq %ds, %rax;\n\t"	\
	"pushq %rax;    \n\t"	\
	"movq %es, %rax;\n\t"	\
	"pushq %rax;    \n\t"	\
	"movq %fs, %rax;\n\t"	\
	"pushq %rax;    \n\t"	\
	"movq %gs, %rax;\n\t"	\
	"pushq %rax;"		\
	"movq $0x10, %rax;\n\t"	\
	"movq %rax, %ds;\n\t"	\
	"movq %rax, %es;\n\t"	\
	"movq %rax, %fs;\n\t"	\
	"movq %rax, %gs;\n\t"


#define IRQ_NAMEN(nr) nr##_interrupt(void)
#define IRQ_NAME(nr)  IRQ_NAMEN(irq##nr)


#define build_irq(nr)				\
	void IRQ_NAME(nr);			\
	__asm__ (				\
		".globl irq"#nr"_interrupt\n\t;"\
		"irq"#nr"_interrupt:	\n\t"	\
		"cli\n\t"			\
		IRQ_SAVE_ALL()			\
		/* arguments for do_irq */	\
		"movq %rsp, %rdi\n\t"		\
		"movq $"#nr", %rsi\n\t"		\
		"leaq ret_intr(%rip), %rax\n\t"	\
		"pushq %rax\n\t"		\
		"jmp do_irq\n\t"		\
	);


#define MAX_IRQ_NR 0x60

struct irq_entry {
	void (*handler) (void);
};

extern struct irq_entry irq_table[MAX_IRQ_NR];

#endif

/* offsets value in stack */
#define off_gs	0
#define off_fs 	1
#define off_es 	2
#define off_ds 	3
#define off_r15	4
#define off_r14	5
#define off_r13	6
#define off_r12	7
#define off_r11	8
#define off_r10	9
#define off_r9	10
#define off_r8	11
#define off_rdi	12
#define off_rsi	13
#define off_rbp	14
#define off_rbx 15
#define off_rdx	16
#define off_rcx	17
#define off_rax	18

#define off_handler 	19
#define off_errcode	20
#define off_rip 	21
#define off_rflags	22
#define off_rsp		23
#define off_ss		24

#define GS 	0
#define FS 	8
#define ES 	16
#define DS 	24
#define R15 	32
#define R14 	40
#define R13 	48
#define R12 	56
#define R11 	64
#define R10 	72
#define R9 	80
#define R8 	88
#define RDI	96
#define RSI 	104
#define RBP 	112
#define RBX 	120
#define RDX 	128
#define RCX 	136
#define RAX 	144

#define HANDLER 152
#define ERRCODE 160

#define RIP 	168
#define RFLAGS 	176

/* maybe, maybe, well... */
#define RSP 	184
#define SS 	192

#endif

